home *** CD-ROM | disk | FTP | other *** search
- TITLE SDIR - SORTED DIRECTORY COMMAND, Version 2.4
- PAGE 64,132 ; JAN 1983
- COMMENT |
- SDIR [d:][path][filename[.ext]] [options] 2.4
- [filespec] same as for DIR command
-
- [options] * /A - List hidden files.
- * /E - Without screen erase.
- * /P - Pause when screen full.
- /X - Sort by extension.
- /S - Sort by size.
- /D - Sort by date/time.
- /N - Do not sort, original order.
-
- Default = *.* sorted by name.ext with screen erase.
- * - Option may be combined with other options.
-
- This source file was created from an object file obtained
- from Gene Plantz's BBS in Chicago. The original file name
- was SD.HEX. I then used DEBUG and CAPTURE to get the first
- dis-assembly which was then edited with WORDSTAR to create
- a source that when assembled using MASM would duplicate the
- original object file.
- Comments have been added and I do hope they are helpful.
- I have made several modifications to the first version and
- am continuing to add comments. This source file is an
- excellent example for anyone wishing to learn 8086/8088
- assembly language. Use at your own risk and feel free to
- share this file with your friends.
- I certainly wish that John Chapman would publish his
- source file. His comments are sure to be more meaningful
- than mine could ever be. Some of the conversion routines
- are very elegant, but difficult to understand. As far as
- I'm concerned, PRINTDD is magic.
- Several modifications have been made. They are:
-
- 1. Filespecs are processed like DIR does.
- 2. No sort option was added. /N
- 3. Pause when screen full option added. /P
- 4. Number of files found is printed.
-
- Ted Reuss
- Houston, TX
-
- SDIR Version 2.2 The GETFREE Subroutine was updated for DOS 2.0
- April 1, 1983 by Jack Y. Fong
- Changes are denoted by "JYF" at the end of changed lines.
-
-
- SDIR Version 2.3:
- Added display of current directory name and volume name
- in header lines for DOS Release 2.0.
- Added total of file sizes for the displayed files.
- This is helpful in DOS 2.0 since it allows you to determine
- the number of bytes used by all the files in a root or
- subdirectory (or used by a specified subset of
- the files in a root or subdirectory).
-
- John F. Ratti 29 June, 1983
- Changes are denoted by "2.3" at the end of the changed lines.
-
- SDIR Version 2.4:
- Added display of attribute byte. The column 'ATR' will display
- up to 4 attribute codes. The codes are as follows:
- A - Archive bit is off (file has been archived)
- H - Hidden bit is on (file is hidden)
- R - Read-only bit is on (file is read-only)
- S - System bit is on (file is a system file)
- Corrected display of hidden, system, read-only and directory
- entries when /a option is specified.
- Added pathname capability. Any pathname that DIR will accept
- will work. The code should have been rewritten, rather than
- modified. The resulting code is somewhat obtuse, and I
- apologize for it. I plan to write a proper pathname
- parser. When I do, I'll incorporate it into SDIR.
- This version MUST be used under MS-DOS release 2.0.
- John F. Ratti 03 July, 1983
- Changes are denoted by "2.4" at the end of the changed lines.
- |
-
- SUBTTL EQUATES & STRUCTURES
- PAGE
- IF1
- DOSCALL MACRO FUNC,PARM1
- .xcref
- F_C = FUNC
- IFNB <PARM1>
- IF F_C EQ 2 OR (F_C GE 4 AND F_C LE 6) OR F_C EQ 14 OR F_C EQ 46
- MOV DL,PARM1
- ELSE
- MOV DX,OFFSET PARM1
- ENDIF
- ENDIF
- MOV AH,FUNC
- INT 21H
- .cref
- ENDM
- ENDIF
- .SALL ;supress all macro expansions
- ; PC-DOS INTERRUPT 21H FUNCTION CODES
- ;
- @CHROUT EQU 2 ;display char in DL
- @KEYIN EQU 8 ;kybd input w/o echo
- @STROUT EQU 9 ;print string terminated with $
- @CKEYIN EQU 12 ;clr kybd bufr & do inp.func in AL
- @OPEN EQU 15 ;open XFCB 2.4
- @SRCH1 EQU 17 ;search for first dir entry
- @SRCH2 EQU 18 ;search for next dir entry
- @GETDSK EQU 25 ;get default disk drive
- @SETDTA EQU 26 ;set disk transfer addr
- @FATAD2 EQU 28 ;get FAT of drive # in DL
- @PARSEF EQU 41 ;parse filename
- @GETDTE EQU 42 ;get system date
- @GETTME EQU 44 ;get system time
- @GETVER EQU 30H ;get version number JYF
- @CTLBRK EQU 33H ;get/set ctrl/break checking 2.4
- @DSKFSP EQU 36H ;get disk free space JYF
- @CHDIR EQU 3BH ;change directory 2.4
- @CHMOD EQU 43H ;change/get file mode 2.4
- @GETCD EQU 47H ;get current directory 2.3
- @FIND1 EQU 4EH ;find first dir. entry (DOS 2.0) 2.4
- @FIND2 EQU 4FH ;find next dir entry (DOS 2.0) 2.4
-
- CR EQU 0DH ;carriage return
- LF EQU 0AH ;line feed
- FCB_1 EQU 5CH ;fcb for parameter 1
- PARAM_L EQU 80H ;# characters in PARAM_B
- PARAM_B EQU 81H ;DOS cmd parameter buffer.
-
- ; PC-DOS packed date <yyyyyyym mmmddddd>
- P_DTE RECORD P_YR:7,P_MO:4,P_DY:5
- ; PC-DOS packed time <hhhhhmmm mmmsssss>
- P_TME RECORD P_HR:5,P_MI:6,P_2S:5
-
- DIR RECORD P_YR:7,P_MO:4,P_DY:5
- ; PC-DOS packed time <hhhhhmmm mmmsssss>
- P_TME RECORD P_HR:5,P_MI:6,P_2S:5
-
- DIRNTRY STRUC ;directory entry structure
- LNK DW 0 ;ptr to next entry
- NAM DB 8 DUP(0),'.' ;filename
- EXT DB 3 DUP(0) ;extension
- TME DW 0 ;time
- DTE DW 0 ;date
- SZL DW 0 ;low word of size
- SZH DW 0 ;high word of size
- ATR DB 0 ;attribute byte 2.4
- DIRNTRY ENDS
-
- SUBTTL DATA AREA & INITIALIZATION
- PAGE
- SDIR SEGMENT PUBLIC 'CODE'
- ASSUME CS:SDIR,DS:SDIR,ES:SDIR
- ORG 100H
- MAIN PROC FAR
- JMP STARTS
-
- DIRLNK DW DIRBUF ;ptr to next opening in DIRBUF
- C1LNK DW 0 ;ptr to row 1, column 1
- C2LNK DW 0 ;ptr to row 1, column 2
- NBRFILS DW 0 ;# of files or detail lines
- SRTFLG DB 0 ;if = 0 then sort else no sort
- CLSFLG DB 0 ;if = 0 then clear screen
- EXTFLG DB 0 ;if <> 0 then sort by ext
- SIZFLG DB 0 ;if <> 0 then sort by size
- DTEFLG DB 0 ;if <> 0 then sort by date/time
- PSEFLG DB 0 ;if <> 0 then pause if screen full
- LPERSCR EQU 25 ;Lines per screen
- LINCNT DB LPERSCR-5 ;Number of lines left
- PSEMSG DB 'Strike a key when ready . . . $'
-
- HDNG1 DB 'SDIR: Sorted DIRectory listing, Version 2.4 '; 2.3
- DB 'Volume ' ; 2.3
- VOLNAME DB ' ' ; 2.3
- D_MM DW '00' ;Month
- DB '/'
- D_DD DW '00' ;Day
- DB '/'
- D_YY DW '00' ;Year
- DB ' '
- T_HH DW '00' ;Hours
- DB ':'
- T_MM DW '00' ;Minutes
- DB CR,LF,'$' ; 2.3
- HDNG2 DB 32 DUP(' ') ; 2.3
- DB 'Directory of ' ; 2.3
- HDRVE DB '@:' ; 2.3
- DIRNAME DB '\',69 DUP(0) ; directory name 2.4
- DB LF,LF,CR,'$' ; 2.3
- CRLF DB CR,LF,'$'
- LFLFCR DB LF,LF,CR,'$' ;literal for a blank line 2.3
- HDNG3 DB 'FILESPEC.EXT BYTES ATR -LAST CHANGE-$'
- DB 8 DUP(' ')
- SPACES DB '$'
- HDNG4 DB ' Bytes in $' ; 2.3
- HDNG5 DB ' File(s); ','$' ; 2.4
- HDNG6 DB ' bytes free.',CR,LF,'$' ; 2.4
-
- SUBTTL DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
- PAGE
-
- DB 'PATH NAME='
- PATHD DB '@:'
- PATH DB 64 DUP(0) ;hold area for pathname 2.4
-
- XFCB DB -1,7 DUP(0),11 DUP('?'),25 DUP(0)
- ATTRIB EQU XFCB+6 ;file attribute
- DRVNUM EQU ATTRIB+1 ;drive # (1=A, 2=B, etc.)
-
- DTA DB 40 DUP(0) ;Disk Transfer Area used
- XNAME EQU DTA+8 ;volume name 2.4
- FILNAME EQU DTA+30 ;by FIND for the 2.4
- FILTIME EQU DTA+22 ;directory search. 2.4
- FILSIZE EQU DTA+26 ; 2.4
- FILATTR EQU DTA+21 ;(file attribute byte) 2.4
-
- FREESPC DW 0 ;Free space entry.
- DB '*FREE SPACE*',4 DUP(0)
- LOSIZE DW 0 ;of free space
- HISIZE DW 0 ;of free space
-
- LOTOTAL DW 0 ;total size of all files: low word 2.3
- HITOTAL DW 0 ;total size of all files: high word 2.3
-
- PATHLEN DW 0 ;length of subdirectories in pathname 2.4
- HOLDATR DB 0 ;hold area for XFCB attribute byte 2.3
- HOLDLEN DW 0 ;hold area for length of directory name 2.3
-
- DBLCNT DW 0 ;current offset into DOUBLE 2.4
- DOUBLE DB 8 DUP(' '),'$' ;destination for PRINTDX 2.4
-
- PRTATR DB 5 DUP(' '),'$' ;area to build ATR for printing 2.4
- INITATR DB 5 DUP(' ') ;used to re-init ATR 2.4
-
- PRTDIR DB ' <DIR>$' ;literal used to denote directories 2.4
- ALLF DB '*.*' ;literal for displaying all files 2.4
- PATHALL DB '\*.*',0 ;same as above for subdirectories 2.4
-
- DRVNBR DB 0 ;place to hold working drive number 2.4
-
- CURDSK DB '@:\' ;hold area for current dirname so we can2.4
- CURDIR DB 64 DUP(0) ;restore it later 2.4
-
- PATHNF DB 'Path not found$' ;error message literal 2.4
-
- SUBTTL MAIN PROGRAM SECTION
- PAGE
- STARTS:
- PUSH DS ;Set up the
- XOR AX,AX ; stack for a
- PUSH AX ; return to DOS.
- CALL GETARGS ;Process arguments
- CALL SRCHDIR ;Search directory
- CMP SRTFLG,0 ;Check if any sort
- JZ A1 ; option selected.
- CALL LNKDIRB ;Leave in original
- JMP SHORT A2 ; directory order.
- A1: CALL SRTDIRB ;Sort by major key
- A2: CALL GETFREE ;Get free space
- CALL SPLTLST ;Set up for 2 columns
- CALL PRTHDNG ;Print headings
- CALL PRTDRVR ;Print detail lines
- CALL PRTNFLS ;Print byte total and # of files 2.3
- RET ;Return to DOS
- MAIN ENDP
-
- SUBTTL GETARGS - PROCESS ARGUMENTS
- PAGE
- GETARGS PROC NEAR
- MOV DI,PARAM_L ;point to command buffer length 2.4
- XOR CH,CH ;clear high-order byte 2.4
- MOV CL,BYTE PTR [DI] ;get length 2.4
- JCXZ G24F ;jump if no param provided 2.4
- INC DI ;point to command buffer 2.4
- MOV AL,' ' ;we'll search for the first non-blank 2.4
- CLD ;search forward 2.4
- REPE SCASB ;find first non-blank 2.4
- JE G24F ;all blanks: treat like no parm provided2.4
- INC CX ;and adjust length 2.4
- DEC DI ;adjust offset 2.4
- MOV SI,DI ;save offset of first non-blank 2.4
- MOV DX,CX ;save cx 2.4
- MOV AL,'/' ;search for a slash 2.4
- CLD ;clear direction flag 2.4
- REPNE SCASB ;search for a slash 2.4
- JCXZ G24A ;jump if slash not found 2.4
- INC CX ;adjust cx if slash found 2.4
- G24A: NEG CX ;subtract count from original length 2.4
- ADD CX,DX ;to get length of drive+path 2.4
- JCXZ G24F ;if 0, only options specified 2.4
- MOV DI,OFFSET PATH ;point to path name hold area 2.4
- CMP BYTE PTR [SI+1],':' ;was drive number specified? 2.4
- JNE G24B ;No, go move the path 2.4
- INC SI ;point past drive number 2.4
- INC SI ;point past : 2.4
- DEC CX ;adjust... 2.4
- DEC CX ;...length 2.4
- JNZ G24B ;if any characters remain process them 2.4
- G24F: MOV SI,OFFSET ALLF ;point to the all-files literal 2.4
- MOV DI,OFFSET PATH ;the path needs it 2.4
- MOV CX,3 ;length of literal 2.4
- CLD ;to assure forward direction 2.4
- REP MOVSB ;move the literal 2.4
- JMP G24C ;now process normally 2.4
- G24B: CLD ;clear direction flag 2.4
- MOV DX,CX ;save the length 2.4
- REP MOVSB ;and move the pathname to path 2.4
- CMP DX,1 ;is length of pathname 1? 2.4
- JNE G24C ;no 2.4
- CMP PATH,'\' ;is the only character a backslash? 2.4
- JNE G24C ;no 2.4
- MOV SI,OFFSET ALLF ;point to the all-files literal 2.4
- MOV DI,OFFSET PATH+1 ;the path needs it 2.4
- MOV CX,3 ;length of literal 2.4
- CLD ;to assure forward direction 2.4
- REP MOVSB ;move the literal 2.4
- G24C: MOV SI,PARAM_B ;point to cmd buffer 2.4
- MOV DI,OFFSET DRVNUM ;point to FCB 2.4
- MOV AL, 1111B ;Select parse options
- DOSCALL @PARSEF ;Parse filename
- CMP BYTE PTR [DI],0 ;If <> 0 then
- JNZ B1 ; not default drive
- DOSCALL @GETDSK ;AL <- default disk
- INC AL ;Increment drive #
- STOSB ;Save drive #
- B1: MOV AL,DRVNUM ;get drive number 2.4
- MOV DRVNBR,AL ;save as working drive number 2.4
- ADD PATHD,AL ;convert drive number to ascii 2.4
- XOR CX,CX ;clear cx just in case... 2.4
- MOV AX,0 ;load "get attribute" subfunction code 2.4
- DOSCALL @CHMOD,PATHD ;get attribute of the current path in cx2.4
- OR AL,AL ;check for error 2.4
- JNZ G24X ;if so, it's not a directory 2.4
- TEST CX,10H ;is it a directory? 2.4
- JZ G24X ;no 2.4
- MOV DI,OFFSET PATH ;we need to find the end of PATH 2.4
- MOV CX,64 ;which can be up to 64 bytes long... 2.4
- MOV AL,0 ;...so we'll search for a 0 2.4
- CLD ;search forward 2.4
- REPNE SCASB ;find the end of PATH 2.4
- DEC DI ;point di at the zero 2.4
- MOV SI,OFFSET PATHALL ;point to literal 2.4
- MOV CX,5 ;literal is 5 bytes long 2.4
- CLD ;i'm a coward 2.4
- REP MOVSB ;now move the literal to the path 2.4
- G24X: MOV CX,64 ;up to 64 characters in a pathname 2.4
- MOV AL,'\' ;we'll search for the last backslash 2.4
- MOV DI,OFFSET PATH+63 ;point to the end of the pathname 2.4
- STD ;search backwards 2.4
- REPNE SCASB ;for the last backslash 2.4
- MOV PATHLEN,CX ;and save path length 2.4
- CMP PATH,'\' ;is first path character a backslash? 2.4
- JNE G24D ;no, full path not specified 2.4
- MOV CX,PATHLEN ;get the length of the subdirectories 2.4
- MOV SI,OFFSET PATH ;point to path 2.4
- MOV DI,OFFSET DIRNAME ;and to dest 2.4
- CLD ;just in case 2.4
- REP MOVSB ;move the pathname 2.4
- JMP G24E ;bypass the rest of this 2.4
- G24D: MOV SI,OFFSET DIRNAME+1 ;point to directory name field 2.4
- MOV DL,BYTE PTR DRVNBR ;pick up drive number 2.4
- DOSCALL @GETCD ;get the current directory 2.4
- MOV CX,PATHLEN ;if pathlen is zero, no subdirectories 2.4
- JCXZ G24E ;so don't concatenate path 2.4
- MOV CX,64 ;we're going to find the end of... 2.4
- MOV AL,0 ;...DIRNAME so we can concatenate... 2.4
- MOV DI,OFFSET DIRNAME ;...the path subdirectories to it 2.4
- CLD ;search forwards 2.4
- REPNE SCASB ;search for a 0 2.4
- DEC DI ;point back to the zero 2.4
- DEC DI ;point to last character of current dir 2.4
- CMP BYTE PTR [DI],'\' ;is the last character a backslash? 2.4
- JNE G24Z ;no, it's not a root directory 2.4
- INC DI ;adjust pointer 2.4
- JMP G24Y ;and skip extra-separator stuff 2.4
- G24Z: INC DI ;adjust pointer 2.4
- MOV AL,'\' ;get a literal 2.4
- STOSB ;to separate the 2 concatenated parts 2.4
- G24Y: MOV CX,PATHLEN ;get length of subdirectories 2.4
- MOV SI,OFFSET PATH ;move from path to dirname 2.4
- CLD ;forward move 2.4
- REP MOVSB ;now concatenate the dir + pathnames 2.4
- G24E: MOV AL,0 ;read ctrl/break state into dl 2.4
- DOSCALL @CTLBRK ;read status 2.4
- PUSH DX ;save status 2.4
- MOV AL,1 ;prepare to set ctl/break state... 2.4
- MOV DL,0 ;...to OFF... 2.4
- DOSCALL @CTLBRK ;...so we won't mess up the current dir 2.4
- MOV DL,BYTE PTR DRVNBR ;get drive number 2.4
- ADD CURDSK,DL ;convert to ascii 2.4
- ADD HDRVE,DL ;convert to ascii 2.4
- MOV SI,OFFSET CURDIR ;point to current directory save area 2.4
- DOSCALL @GETCD ;get and save current directory 2.4
- DOSCALL @CHDIR,HDRVE ;temporarily set current directory 2.4
- CMP AL,3 ;check for error return 2.4
- JNE G24Q ;jump if no error 2.4
- DOSCALL @STROUT,PATHNF ;issue 'path not found message' 2.4
- INT 20H ;and get lost 2.4
- G24Q: MOV DL,BYTE PTR DRVNBR ;get drive number 2.4
- MOV SI,OFFSET DIRNAME+1 ;point to dirname 2.4
- DOSCALL @GETCD ;now get the dirname without '\..'s 2.4
- DOSCALL @CHDIR,CURDSK ;now reset the current directory 2.4
- MOV AL,1 ;set ctrl/break state... 2.4
- POP DX ;...to previous value 2.4
- DOSCALL @CTLBRK ;and do it 2.4
- MOV DI,OFFSET DIRNAME ;point to directory name field again 2.4
- MOV CX,64 ;name can be up to 64 bytes long 2.4
- MOV AL,0 ;name is terminated by a zero 2.4
- CLD ;just in case 2.4
- REPNE SCASB ;search for the end 2.4
- MOV AX,64 ;get constant 2.4
- SUB AX,CX ;subtract remaining count 2.4
- SHR AX,1 ;divide result by 2 2.4
- MOV HOLDLEN,AX ;and save result 2.4
- DEC DI ;adjust pointer 2.4
- MOV CX,4 ;load length of literal 2.4
- MOV SI,OFFSET LFLFCR ;point to literal 2.4
- CLD ;just in case 2.4
- REP MOVSB ;and terminate the dirname with literal 2.4
- MOV SI,PARAM_L ;SI <- ptr cmd length
- MOV CH,0
- MOV CL,[SI] ;CL <- # chars in cmd
- JCXZ B10
- B2: INC SI ;Point to next char
- CMP BYTE PTR [SI],'/'
- JNZ B8 ;If not a slash
- MOV AL,[SI+1] ;AL <- option letter
- AND AL,0DFH ;Force to upper-case
- CMP AL,'A' ;Hidden & system & directory files?
- JNZ B3 ;Nope, try next one.
- MOV HOLDATR,2+4+16 ;Hidden & system & directory
- B3: CMP AL,'E' ;Without screen erase?
- JNZ B4 ;Nope, try next one.
- MOV CLSFLG,AL
- B4: CMP AL,'S' ;Sort by size?
- JNZ B5 ;Nope, try next one.
- MOV SIZFLG,AL
- B5: CMP AL,'D' ;Sort by date/time?
- JNZ B6 ;Nope, try next one.
- MOV DTEFLG,AL
- B6: CMP AL,'X' ;Sort by extension?
- JNZ B7 ;Nope, try next one.
- MOV EXTFLG,AL
- B7: CMP AL,'N' ;Original order?
- JNZ B8 ;Nope, try next one.
- MOV SRTFLG,AL
- B8: CMP AL,'P' ;Pause when screen full?
- JNZ B9 ;Nope, try next one.
- MOV PSEFLG,AL
- B9: LOOP B2 ;Test for another param.
- B10: RET
- GETARGS ENDP
-
- SUBTTL SRCHDIR - SEARCH DIRECTORY
- PAGE
- SRCHDIR PROC NEAR
-
- DOSCALL @SETDTA,DTA ;Set DTA for dir. search 2.3
- MOV CX,11 ;we'll move 11... 2.4
- MOV AL,'?' ;...question marks... 2.4
- MOV DI,OFFSET XFCB+8 ;...to the XFCB... 2.4
- CLD ;...in case the filename is crashed... 2.4
- REP STOSB ;...so that we can search for the volid 2.4
- MOV BYTE PTR ATTRIB,8 ;set attribute byte and... 2.3
- DOSCALL @SRCH1,XFCB ;get the volume name 2.3
- MOV SI,OFFSET XNAME ;point to filename within xfcb 2.4
- MOV CX,11 ;load length of volume name 2.3
- MOV DI,OFFSET VOLNAME ;point to destination field in HDNG1 2.3
- CLD ;forward, march 2.3
- REP MOVSB ;move the volume name 2.3
- MOV DI,OFFSET DIRNAME ;point to the directory name again 2.3
- MOV CL,HOLDATR ;get the real attribute byte 2.4
- XOR CH,CH ;clear the high-order byte 2.4
- DOSCALL @FIND1,PATHD ;First call to search dir. 2.4
- C1: OR AL,AL
- JNZ C2 ;Not found, quit looking.
- MOV BX,DIRLNK ;BX <- base of DIRBUF
- LEA DI,[BX].NAM ;point to beginning of dirntry 2.4
- MOV SI,OFFSET FILNAME
- MOV CX,12 ;length of filename 2.4
- CMP BYTE PTR [SI],'.' ;is first character a period? 2.4
- JNE C24A ;no, it's not a special case 2.4
- MOVSB ;move it to the buffer 2.4
- DEC CX ;adjust count 2.4
- CMP BYTE PTR [SI],'.' ;is next character a period? 2.4
- JNE C24A ;no, let normal routine pad the rest 2.4
- MOVSB ;move it to the buffer 2.4
- DEC CX ;adjust count 2.4
- C24A: CMP BYTE PTR [SI],0 ;is it a zero? 2.4
- JNE C24B ;no 2.4
- MOV AL,' ' ;load a space into al 2.4
- REP STOSB ;and blank out the rest of the name 2.4
- JMP C24X ;and go get other fields 2.4
- C24B: CMP BYTE PTR [SI],'.' ;is it a period? 2.4
- JNE C24C ;no, process it 2.4
- MOV DX,CX ;save CX 2.4
- SUB CX,4 ;determine number of spaces needed 2.4
- SUB DX,CX ;adjust saved CX 2.4
- MOV AL,' ' ;get a space 2.4
- REP STOSB ;and pad out the name 2.4
- MOV CX,DX ;restore CX 2.4
- C24C: MOVSB ;move the character to the buffer 2.4
- DEC CX ;adjust count 2.4
- JNZ C24A ;and loop if anything's left to process 2.4
- C24X: MOV SI,OFFSET FILTIME ;exit point for filename routine 2.4
- MOVSW ;Move time to DIRBUF
- MOVSW ;Move date to DIRBUF
- MOV SI,OFFSET FILSIZE
- MOVSW ;Move size to DIRBUF
- MOVSW
- MOV SI,OFFSET FILATTR ;point to file attribute byte 2.4
- MOVSB ;and move it to dirntry 2.4
- ADD BX,SIZE DIRNTRY ;Point to next entry
- MOV DIRLNK,BX ;Save ptr
- INC NBRFILS ;Increment file count
- MOV CL,HOLDATR ;get the real attribute byte 2.4
- XOR CH,CH ;clear the high-order byte 2.4
- DOSCALL @FIND2,PATHD ;Search for next file 2.4
- JMP C1 ;Loop for next one
- C2: RET
- SRCHDIR ENDP
-
- SUBTTL SRTDIRB - SORTS ENTRIES IN DIRBUF
- PAGE
- SRTDIRB PROC NEAR ;Sorts directory entries in DIRBUF
- MOV DI,OFFSET DIRBUF ;Point to DIRBUF
- D1: CMP DI,DIRLNK ;Are there anymore?
- JNC D8 ;NO, exit
- MOV SI,OFFSET C1LNK ;Start with column 1 ptr
- D2: MOV BX,SI
- MOV SI,[BX] ;SI<-ptr to next entry
- OR SI,SI
- JZ D7 ;if link=0
- MOV AX,SI
- MOV DX,DI
- XOR CL,CL ;CL <- 0
- CMP CL,SIZFLG
- JNZ D5 ;If sort by size
- CMP CL,DTEFLG
- JNZ D4 ;If sort by date/time
- CMP CL,EXTFLG
- JNZ D3 ;If sort by ext
- LEA SI,[SI].NAM
- LEA DI,[DI].NAM
- MOV CX,1+SIZE NAM+SIZE EXT ;# of bytes
- JMP SHORT D6
- D3: LEA SI,[SI].EXT ;Sort by extension
- LEA DI,[DI].EXT
- MOV CX,SIZE EXT ;# of bytes
- JMP SHORT D6
- D4: LEA SI,[SI].DTE ;Sort by date/time
- LEA DI,[DI].DTE
- MOV CX,2 ;# of words
- STD
- REPZ CMPSW
- MOV DI,DX
- MOV SI,AX
- JBE D2
- JMP SHORT D7
- D5: LEA SI,[SI].SZH ;Sort by size
- LEA DI,[DI].SZH
- MOV CX,2 ;# of words
- STD
- REPZ CMPSW
- MOV DI,DX
- MOV SI,AX
- JBE D2
- JMP SHORT D7
- D6: CLD ;Sort by name.ext
- REPZ CMPSB
- MOV DI,DX
- MOV SI,AX
- JBE D2
- D7: MOV [DI],SI
- MOV [BX],DI
- ADD DI,SIZE DIRNTRY ;Point to next entry
- JMP D1
- D8: RET
- SRTDIRB ENDP
-
- SUBTTL
- PAGE
- ; LNKDIRB - LINKS ENTRIES IN DIRBUF
-
- LNKDIRB PROC NEAR ;LINK ENTRIES IN DIRBUF
- MOV DI,OFFSET DIRBUF
- MOV C1LNK,DI ;Point to 1st entry
- MOV CX,NBRFILS ;Set loop counter
- DEC CX
- LNK1: MOV BX,DI
- ADD DI,SIZE DIRNTRY ;Offset to next entry
- MOV [BX],DI ;Store ptr
- LOOP LNK1 ;Link next entry
- MOV [DI],CX ;Last ptr <- null
- RET
- LNKDIRB ENDP
-
- ; SPLTLST - SPLITS LINKED LIST IN HALF
-
- SPLTLST PROC NEAR
- MOV CX,NBRFILS ;Get # of entries
- SAR CX,1 ; and divide by 2
- JZ F2 ;if NBRFILS < 2
- ADC CL,0 ;Account for odd #
- MOV BX,OFFSET C1LNK
- F1: MOV BX,[BX] ;Chain thru list to
- LOOP F1 ; last row of column 1.
- MOV AX,[BX] ;Get ptr to 1st row of col 2
- MOV C2LNK,AX ; C2LNK <- R1,C2 ptr
- MOV [BX],CX ;Last row of col 1 <- null
- F2: RET
- SPLTLST ENDP
-
- SUBTTL GETFREE - GET DISK FREE SPACE
- PAGE
- GETFREE PROC NEAR ;cluster = allocation unit
- MOV DL,DRVNBR ;Get drive #
- PUSH DS ;Save DS
- DOSCALL @GETVER ;get DOS version number JYF
- CMP AL,2 ;is this version 2.0 or higher? JYF
- JGE E4 ;yes JYF
- ;no JYF
- DOSCALL @FATAD2 ;Get FAT info from DOS
- MOV AH,0 ;AL = sector size
- XCHG CX,DX ;Sector size times the
- MUL DX ; # sectors/cluster
- PUSH AX ;Save cluster size
- XOR AX,AX ;Unused clusters = 0
- MOV SI,2 ;Skip first 3 clusters
- E1: MOV DI,SI ;DI <- cluster #
- SHR DI,1 ;Divide cluster number
- ADD DI,SI ; by 1.5
- MOV DI,[BX+DI] ;Fetch from FAT
- TEST SI,1 ;Test if even or odd
- JZ E2 ;If even then skip
- SHR DI,1 ; else if odd
- SHR DI,1 ; right justify the
- SHR DI,1 ; cluster number.
- SHR DI,1
- E2: AND DI,0FFFH ;Mask the low 12 bits
- JNZ E3 ;If not 0 then skip, else
- INC AX ; increment counter.
- E3: INC SI ;Point to next cluster
- LOOP E1 ; and go check it.
- POP CX ;Get cluster size, times
- MUL CX ; # of free clusters
- JMP E5 ;skip processing for DOS 2.0 JYF
- E4: ;processing for DOS 2.00 JYF
- DOSCALL @DSKFSP ;get disk free space JYF
- MUL BX ;AX (sectors/clustor) * BX (free clustors) JYF
- MOV DX,AX ; JYF
- MUL CX ;AX * CX (bytes/clustor) JYF
- E5: ; JYF
- POP DS ;Restore DS
- MOV LOSIZE,AX ;Save the 32 bit
- MOV HISIZE,DX ; binary free space
- RET
- GETFREE ENDP
-
- SUBTTL PRTHDNG - PRINT HEADINGS
- PAGE
- PRTHDNG PROC NEAR
- MOV AL,CLSFLG
- OR AL,AL
- JNZ G1 ;If not erase screen
- SUB CX,CX
- MOV DX,24*256+79 ;row=24 col=79
- MOV BH,7 ;Video mode
- MOV AX,0600H
- INT 10H ;BIOS video call
- SUB DX,DX
- MOV AH,2 ;Clear screen
- MOV BH,0
- INT 10H ;BIOS video call
- G1: MOV AL,DRVNBR ;Get drive #
- DOSCALL @GETDTE ; CX<-year, DH<-month, DL<-day
- MOV AL,DH
- AAM
- XCHG AL,AH
- OR D_MM,AX ;Fold into month
- MOV AL,DL
- AAM
- XCHG AL,AH
- OR D_DD,AX ;Fold into day
- MOV AX,CX
- SUB AX,1900
- AAM
- XCHG AL,AH
- OR D_YY,AX ;Fold into year
- DOSCALL @GETTME ; CH<-hours, CL<-minutes
- MOV AL,CH ;AL<-binary hours
- AAM ;Convert AL to two
- XCHG AL,AH ; BCD digits in AX.
- OR T_HH,AX ;Fold into hours
- MOV AL,CL ;AL<-binary minutes
- AAM ;Convert AL to two
- XCHG AL,AH ; BCD digits in AX.
- OR T_MM,AX ;Fold into minutes
- DOSCALL @STROUT,HDNG1 ;Print main heading
- MOV DX,OFFSET HDNG2 ;point to 2nd heading 2.3
- ADD DX,HOLDLEN ;add offset length to center DIRNAME 2.3
- DOSCALL @STROUT ;Print subheading 2.3
- DOSCALL @STROUT,HDNG3 ;Print column 1 heading
- CMP WORD PTR C2LNK,0
- JZ G2 ;If not 2 columns
- DOSCALL @STROUT,SPACES-3 ;Print 3 spaces 2.4
- DOSCALL @STROUT,HDNG3 ;Print column 2 heading
- G2: DOSCALL @STROUT,CRLF ;Start a new line
- RET
- PRTHDNG ENDP
-
- SUBTTL PRINT DETAIL LINES
- PAGE
- PRTDRVR PROC NEAR ;Driver routine
- MOV BX,C1LNK
- OR BX,BX ;more to print?
- JZ H2 ; no, return
- MOV AX,[BX]
- MOV C1LNK,AX
- CALL PRTDTL ;print column one
- MOV BX,C2LNK
- OR BX,BX
- JZ H1 ;If no column 2 entry
- DOSCALL @STROUT,SPACES-3 ;print 3 spaces 2.4
- MOV AX,[BX]
- MOV C2LNK,AX
- CALL PRTDTL ;print column two
- H1: DOSCALL @STROUT,CRLF
- CMP PSEFLG,0 ;Check for pause option
- JZ PRTDRVR ;Nope, continue
- DEC LINCNT ;Decrement line counter
- JNZ PRTDRVR ;If page not full?
- MOV LINCNT,LPERSCR-2 ;Reset to # lines/screen
- DOSCALL @STROUT,PSEMSG ;Display pause message.
- MOV AL,@KEYIN ;Specify input function
- DOSCALL @CKEYIN ;Wait for key press
- DOSCALL @STROUT,CRLF ;Set to new line
- JMP PRTDRVR ;Go do the next line
- H2: RET
- PRTDRVR ENDP
-
- PRTDTL PROC NEAR ;Prints file.ext, size, date & time
- MOV CX,1+SIZE NAM+SIZE EXT ; 2.4
- SUB DI,DI ;DI <- 0
- I1: DOSCALL @CHROUT,[BX+DI].NAM
- INC DI ;point to next char.
- LOOP I1 ;go do next char.
- TEST BYTE PTR [BX].ATR,10H ;is it a directory entry? 2.4
- JZ I2 ;no, print size 2.4
- DOSCALL @STROUT,PRTDIR ;yes, print <DIR> instead of size 2.4
- JMP I3 ;and bypass size print 2.4
- I2: PUSH BX ;save entry base
- MOV SI,[BX].SZL ;SI <- low size
- MOV DI,[BX].SZH ;DI <- high size
- ADD LOTOTAL,SI ;add low-order word to total 2.3
- ADC HITOTAL,DI ;and add high-order word to total 2.3
- CALL PRINTDX ;convert size 2.4
- MOV DX,OFFSET DOUBLE+1 ;point past first byte of decimal # 2.4
- DOSCALL @STROUT ;Print size 2.4
- POP BX ;restore entry base
- I3: MOV CX,5 ;we need to move 5 bytes 2.4
- MOV SI,OFFSET INITATR ;to initialize PRTATR 2.4
- MOV DI,OFFSET PRTATR ;with spaces 2.4
- CLD ;just in case 2.4
- REP MOVSB ;now move the spaces 2.4
- TEST BYTE PTR [BX].ATR,10H ;is it a directory file? 2.4
- JNZ I24X ;yes, bypass the other tests 2.4
- MOV DI,OFFSET PRTATR+3 ;point to right side of field 2.4
- STD ;and work backwards 2.4
- TEST BYTE PTR [BX].ATR,20H ;is it an archived file? 2.4
- ;note that the archive bit is set OFF when the file is archived... 2.4
- JNZ I24H ;no, test for hidden file 2.4
- MOV AL,'A' ;get flag character 2.4
- STOSB ;and put it into PRTATR 2.4
- I24H: TEST BYTE PTR [BX].ATR,02H ;is it a hidden file? 2.4
- JZ I24R ;no, test for r/o file 2.4
- MOV AL,'H' ;get flag character 2.4
- STOSB ;and put it into PRTATR 2.4
- I24R: TEST BYTE PTR [BX].ATR,01H ;is it a r/o file? 2.4
- JZ I24S ;no, test for system file 2.4
- MOV AL,'R' ;get flag character 2.4
- STOSB ;and put it into PRTATR 2.4
- I24S: TEST BYTE PTR [BX].ATR,04H ;is it a system file? 2.4
- JZ I24X ;no, exit tests 2.4
- MOV AL,'S' ;get flag character 2.4
- STOSB ;and put it into PRTATR 2.4
- I24X: DOSCALL @STROUT,PRTATR ;Print the attribute characters 2.4
- MOV AX,[BX].DTE ;AX <- packed date
- CALL PRTDTE
- DOSCALL @STROUT,SPACES-1 ;print 1 space 2.4
- MOV AX,[BX].TME ;AX <- packed time
- CALL PRTTME
- RET
- PRTDTL ENDP
-
- SUBTTL PRINTDD - PRINT A DOUBLE WORD IN DI:SI
- PAGE
- PRINTDD PROC NEAR ;Prints a 32 bit integer in DI:SI
- CALL PRINTDX ;format the double word into DOUBLE 2.4
- DOSCALL @STROUT,DOUBLE ;print the digits 2.4
- RET ;and return 2.4
- PRINTDD ENDP ; 2.4
-
- PRINTDX PROC NEAR ;converts integer in DI:SI to decimal 2.4
- MOV DBLCNT,0 ;reset the offset for DOUBLE 2.4
- XOR AX,AX ;Zero out the 2.4
- MOV BX,AX ; working
- MOV BP,AX ; registers.
- MOV CX,32 ;# bits of precision
- J1: SHL SI,1
- RCL DI,1
- XCHG BP,AX
- CALL J6
- XCHG BP,AX
- XCHG BX,AX
- CALL J6
- XCHG BX,AX
- ADC AL,0
- LOOP J1
- MOV CX,1710H ;5904 ?
- MOV AX,BX
- CALL J2
- MOV AX,BP
- J2: PUSH AX
- MOV DL,AH
- CALL J3
- POP DX
- J3: MOV DH,DL
- SHR DL,1 ;Move high
- SHR DL,1 ; nibble to
- SHR DL,1 ; the low
- SHR DL,1 ; position.
- CALL J4
- MOV DL,DH
- J4: AND DL,0FH ;Mask low nibble
- JZ J5 ;If not zero
- MOV CL,0
- J5: DEC CH
- AND CL,CH
- OR DL,'0' ;Fold in ASCII zero
- SUB DL,CL
- PUSH DI ;save DI 2.4
- MOV DI,OFFSET DOUBLE ;point to DOUBLE 2.4
- ADD DI,DBLCNT ;add current offset 2.4
- INC DBLCNT ;bump offset for next time 2.4
- MOV BYTE PTR [DI],DL ;move next digit to DOUBLE 2.4
- POP DI ;restore DI 2.4
- RET ;Exit to caller
- PRINTDX ENDP ; 2.4
-
- J6 PROC NEAR
- ADC AL,AL
- DAA
- XCHG AL,AH
- ADC AL,AL
- DAA
- XCHG AL,AH
- RET
- J6 ENDP
-
- SUBTTL PRINT DATE, TIME & # FILES ROUTINES
- PAGE
- PRTDTE PROC NEAR ;Print packed date in AX as MM/DD/YY
- OR AX,AX
- JNZ K1 ;If date <> 0
- DOSCALL @STROUT,SPACES-8 ;Print 8 spaces
- RET
- K1: PUSH AX
- AND AX,MASK P_MO ;Mask the month,
- MOV CL,P_MO ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- DOSCALL @CHROUT,'/'
- POP AX
- PUSH AX
- AND AX,MASK P_DY ;Mask the day &
- CALL PRTBCD ; print it.
- DOSCALL @CHROUT,'/'
- POP AX
- AND AX,MASK P_YR ;Mask the year,
- MOV CL,P_YR ; set shift count,
- SHR AX,CL ; right justify,
- ADD AX,80 ; add in year bias, &
- ; print it.
- PRTBCD: AAM ;Convert AL to BCD
- OR AX,'00' ;Convert to ASCII
- PUSH AX
- DOSCALL @CHROUT,AH ;High order digit
- POP AX
- DOSCALL @CHROUT,AL ;Low order digit
- RET
- PRTDTE ENDP
-
- PRTTME PROC NEAR ;Print packed time in AX as HH:MM
- OR AX,AX
- JNZ L1
- DOSCALL @STROUT,SPACES-5 ;Print 5 spaces
- RET
- L1: PUSH AX
- AND AX,MASK P_HR ;Mask the hours,
- MOV CL,P_HR ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- DOSCALL @CHROUT,':'
- POP AX
- AND AX,MASK P_MI ;Mask the minutes,
- MOV CL,P_MI ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- RET
- PRTTME ENDP
-
- PRTNFLS PROC NEAR ;print byte total and number of files 2.3
- MOV SI,LOTOTAL ;get low-order word of total 2.3
- MOV DI,HITOTAL ;get high-order word of total 2.3
- CALL PRINTDD ;and print the total 2.3
- DOSCALL @STROUT,HDNG4 ;follow the total with a message 2.3
- MOV SI,NBRFILS ;get # of files
- XOR DI,DI ;zero high order
- CALL PRINTDD ;Print # of files
- DOSCALL @STROUT,HDNG5 ;follow it with a heading
- MOV SI,LOSIZE ;get low-order word of freespace 2.4
- MOV DI,HISIZE ;get high-order word of freespace 2.4
- CALL PRINTDD ;and print freespace 2.4
- DOSCALL @STROUT,HDNG6 ;follow the freespace with explanation 2.4
- RET
- PRTNFLS ENDP
- EVEN
- DIRBUF DIRNTRY <> ;Buffer for directory entries
- SDIR ENDS
- END MAIN